package git

import (
	"fmt"
	"github.com/chmodke/gitmm/config"
	"github.com/chmodke/gitmm/log"
	"github.com/chmodke/gitmm/util"
	"strings"
)

// Sync is entry function
func Sync(upstream config.Remote, origin config.Remote, repo config.Repo, workDir string, progress *util.Progress) bool {
	localRepo, err := util.GetWorkDir(repo.LocalPath(workDir))
	if err != nil {
		return false
	}

	var command string
	var ret bool

	log.Printf("sync %s, from %s to %s.", repo.String(), repo.RemotePath(upstream), repo.RemotePath(origin))
	log.Println("1.1 init local repo.")
	builder := &util.CmdBuilder{}
	builder.Add("git").Add("init")
	ret = util.Status(util.Execute(localRepo, builder.Build()))
	if !ret {
		return ret
	}
	progress.Next()

	log.Printf("2.1 add %s fetch url.", upstream.Name)
	builder.Reset()
	builder.Add("git").Add("remote").Add("add").Add(upstream.Name).Add(repo.RemotePath(upstream))
	ret = util.Status(util.Execute(localRepo, builder.Build()))
	if !ret {
		return ret
	}
	progress.Next()

	log.Printf("2.2 fetch %s all.", upstream.Name)
	builder.Reset()
	builder.Add("git").Add("fetch").Add("--all --prune --tags")
	ret = util.Status(util.Execute(localRepo, builder.Build()))
	if !ret {
		return ret
	}
	progress.Next()

	builder.Reset()
	builder.Add("git").Add("branch -r")
	var out string
	out, ret = util.GetOut(util.Execute(localRepo, builder.Build()))
	if !ret {
		return ret
	}
	progress.Next()

	log.Println("2.3 track all branch.")
	builder.Reset()
	builder.Add("git").Add("branch -f").Add("--track %s").Add("%s/%s")
	tpl := builder.Build()
	for _, s := range strings.Split(out, "\n") {
		branchName, ok := getBranchName(s)
		if ok {
			command = fmt.Sprintf(tpl, branchName, upstream.Name, branchName)
			ret = util.Status(util.Execute(localRepo, command))
		}
	}
	progress.Next()

	log.Printf("2.4 remove %s fetch url.", upstream.Name)
	builder.Reset()
	builder.Add("git").Add("remote").Add("remove").Add(upstream.Name)
	ret = util.Status(util.Execute(localRepo, builder.Build()))
	if !ret {
		return ret
	}
	progress.Next()

	log.Printf("3.1 add %s url.", origin.Name)
	builder.Reset()
	builder.Add("git").Add("remote").Add("add").Add(origin.Name).Add(repo.RemotePath(origin))
	ret = util.Status(util.Execute(localRepo, builder.Build()))
	if !ret {
		return ret
	}
	progress.Next()

	log.Printf("3.2 push %s all.", origin.Name)
	builder.Reset()
	builder.Add("git").Add("push").Add(origin.Name).Add("--all -f")
	ret = util.Status(util.Execute(localRepo, builder.Build()))
	if !ret {
		return ret
	}
	progress.Next()

	builder.Reset()
	builder.Add("git").Add("push").Add(origin.Name).Add("--tags -f")
	ret = util.Status(util.Execute(localRepo, builder.Build()))
	progress.Next()
	return ret
}

/*
getBranchName 从upstream/master获取分支的名称master
*/
func getBranchName(str string) (string, bool) {
	realStr := strings.Trim(str, " ")
	if len(realStr) == 0 {
		return "", false
	}
	if !strings.Contains(realStr, "/") {
		return realStr, false
	}
	return strings.Split(realStr, "/")[1], true
}
